`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2018/04/18 13:47:58
// Design Name: 
// Module Name: FullConnect
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module FullConnect#(
    parameter integer BITWIDTH = 32,
    parameter integer XSHAPE = 32,
    parameter integer YSHAPE = 2
    )
    (
    input clk,
    input reset,
    //input clken,
    input [BITWIDTH * XSHAPE - 1 : 0] xdata,
    input [BITWIDTH * XSHAPE * YSHAPE - 1 : 0] weight,
    input [BITWIDTH * YSHAPE - 1 : 0] bias,
    output reg [BITWIDTH * YSHAPE - 1 : 0] result
    );
    
    wire [BITWIDTH - 1:0] out [0:XSHAPE - 1][0:YSHAPE - 1];
    wire [BITWIDTH - 1:0] biasArr [0:YSHAPE - 1];
    wire [BITWIDTH - 1:0] sum[0:YSHAPE - 1];
    
    // genvar k;
    // generate 
    //     for(k = 0; k < YSHAPE; k = k + 1) begin
    //         assign result[(k+1)* BITWIDTH-1: k*BITWIDTH] = sum[k];
    //     end
    // endgenerate

    genvar i, j;
    generate 
        for(i = 0; i < YSHAPE; i = i + 1) begin
            assign biasArr[i] = bias[(i + 1) * BITWIDTH - 1: i * BITWIDTH];
            for(j = 0; j < XSHAPE; j = j + 1) begin
                Mult#(BITWIDTH) mult(clk, xdata[(j + 1) * BITWIDTH - 1:j * BITWIDTH], weight[(j * YSHAPE + i + 1) * BITWIDTH - 1 : (j * YSHAPE + i) * BITWIDTH], out[j][i]);
            end
        end
    endgenerate
    
    genvar m;
    generate 
    for(m = 0; m < YSHAPE; m = m + 1) begin
        floating_point_acc ipacc(
            .aclk(clk),
            .s_axis_a_tvalid(data_valid),
            .s_axis_a_tdata(b),
            .s_axis_a_tlast(last_mark),
            .m_axis_result_tvalid(res_valid),
            .m_axis_result_tdata(sum[m]),
            .m_axis_result_tlast(res_last_mark)
        );

        reg data_valid;
        wire res_valid;
        reg last_mark;
        reg [BITWIDTH - 1:0] b;
        wire res_last_mark;
        reg [31:0] n;
        // always @(reset) begin
        //     b = biasArr[m];
        //     last_mark = 0;
        //     data_valid = 1;
        //     for(n = 0; n < XSHAPE; n = n + 1) begin
        //         b = out[n][m];
        //         data_valid = 1;
        //         if (n<XSHAPE-1) begin
        //             last_mark = 0;
        //         end else begin
        //             last_mark = 1;
        //         end
        //     end
        //     data_valid = 0;
        //     last_mark = 0;
        //     result[(m+1)* BITWIDTH-1: m*BITWIDTH] = sum[m];
        // end

        // always @(posedge reset) begin
        //     n = 0;
        // end

        always @(posedge clk) begin
            if (n < XSHAPE) begin
                b = out[n][m];
                data_valid = 1;
                last_mark = 0;
                n = n+1;
            end else begin 
                if (n<XSHAPE+1) begin
                    b = biasArr[m];
                    last_mark = 1;
                    data_valid = 1;
                    n = n+1;
                end else begin
                    last_mark = 1;
                    data_valid = 0;
                    if (n<XSHAPE+22) begin
                        n = n+1;
                    end else begin
                        n = 0;
                        result[(m+1)* BITWIDTH-1: m*BITWIDTH] = sum[m];
                    end
                end
            end
        end
    end
    endgenerate

    // always @(posedge clk) begin
    //     if(clken == 1) begin
    //         result = out2;
    //     end
    // end 
    
endmodule
